import BackgroundGaussianBlur from "../class/BackgroundGaussianBlur";
import ScrollAbleContainer from "../class/ScrollAble";
import SVGGraphics from "../class/SVGGraphics";
import TWEEN, {Tween} from "../class/Tween";
import When from "../class/When";
import Map from "../class/Map";
import Snake, {SnakeContainer} from "./Snake";
import Food, {BodyFood, SpeedFood, SensitivityFood, FOOD_CONTAINER_UNIT_SIZE, FoodContainer, FoodEffect, EatAbleFood} from "./Food";
import {
    VIEW_WIDTH,
    VIEW_HEIGHT,
    VIEW_CENTER,
    L_ANI_TIME,
    B_ANI_TIME,
    M_ANI_TIME,
    S_ANI_TIME,
    renderer,
    on,
    TextureGenerator,
    TilingSprite,
} from "./common";

export const ani_ticker = new PIXI.ticker.Ticker();
export const ani_tween = new TWEEN();
export const jump_tween = new TWEEN();

ani_ticker.add(() => {
    ani_tween.update();
    jump_tween.update();
});

export const current_stage = new PIXI.Container();
//加载图片资源
export const loader = new PIXI.loaders.Loader();
loader.add("zz", "/images/snake.jpg");
loader.add("bg", "/images/bg45.jpg");
loader.add('bg_diffuse', '/images/bg66.jpg')
loader.add('bg_normal', '/images/bg66_normal.jpg')
// path_datas.forEach((path_data, i) => {
//     loader.add(path_data.src, path_data.src);
// });
// article_datas.forEach((article_data, i) => {
//     if (article_data.type === "image") {
//         loader.add(article_data.content, article_data.content);
//     }
// });
loader.load();
const loading_text = new PIXI.Text("加载中……", { font: "25px 微软雅黑", fill: "#FFF" });
loading_text.x = VIEW_WIDTH / 2 - loading_text.width / 2;
loading_text.y = VIEW_HEIGHT / 2 - loading_text.height / 2;
current_stage.addChild(loading_text);
loader.on("progress", (loader: PIXI.loaders.Loader, resource: PIXI.loaders.ResourceDictionary) => {
    loading_text.text = `加载中: ${loader.progress}%`;
    loading_text.x = VIEW_WIDTH / 2 - loading_text.width / 2;
    loading_text.y = VIEW_HEIGHT / 2 - loading_text.height / 2;
});

loader.once("complete", renderInit);
/**
 * 数据同步
 * 提供请求花费的时间，通过这个时间来加速本地的效果，从而模拟出当前服务器上的效果
 */
function syncServerData(route, data, callback) {
    var _start_time = Date.now();
    pomelo.request(route, data, function (res_data) {
        if (res_data.code === 500) {
            console.error("ERROR!", route, data, res_data);
            return
        }
        // console.log("ping:", Date.now() - _start_time)
        callback(res_data, () => Date.now() - _start_time);
    });
};

var battlefield_view_width = VIEW_WIDTH;
var battlefield_view_height = VIEW_HEIGHT;

function renderInit(loader: PIXI.loaders.Loader, resource: PIXI.loaders.ResourceDictionary) {
    current_stage.removeChild(loading_text);

    /**背景贴图 */
    var bg_img = new PIXI.extras.TilingSprite(resource["bg"].texture, VIEW_WIDTH, VIEW_HEIGHT);
    // bg_img["normalTexture"] = resource["bg_normal"].texture;
    current_stage.addChild(bg_img);

    var unit_normal_tex = resource["bg_normal"].texture;
    var unit_diffuse_tex = resource["bg_diffuse"].texture;

    // var bg_img = new TilingSprite(unit_diffuse_tex, VIEW_WIDTH, VIEW_HEIGHT, null, null, { y: -5 })
    // bg_img["normalTexture"] = TextureGenerator(renderer, current_stage, unit_normal_tex, bg_img.texture.width, bg_img.texture.height, bg_img.tile_offset_x, bg_img.tile_offset_y)
    // current_stage.addChild(bg_img);


    // 战场基本信息
    const battlefield_level = 2;
    const battlefield_width = Math.pow(2, battlefield_level) * FOOD_CONTAINER_UNIT_SIZE;
    const battlefield_height = Math.pow(2, battlefield_level) * FOOD_CONTAINER_UNIT_SIZE;

    current_stage.addChild(new PIXI.lights.AmbientLight(null, 1.5));

    //生成战场
    var battlefield = new PIXI.Container();
    current_stage.addChild(battlefield);
    bg_img.tilePosition = battlefield.position;

    // 生成蛇容器
    var random_start_point_x = 0//battlefield_width * Math.random()
    var random_start_point_y = 0//battlefield_height * Math.random()
    var snakes = new SnakeContainer();
    battlefield.addChild(snakes);

    // 食物容器
    var foods = new FoodContainer();
    current_stage.addChild(foods);

    //测试背景贴图
    // var bg_normal = new PIXI.Sprite(resource["bg"].texture);
    // bg_normal.anchor.set(.5, .5);
    // bg_normal["normalTexture"] = resource["bg_normal"].texture;
    // battlefield.addChild(bg_normal);
    // ani_ticker.add(() => {
    //     var head_point = my_snake.getHeadPoint();
    //     bg_normal.position = my_snake.getHeadPoint();
    // });



    var my_snake: Snake;
    function my_snake_init(snake_info) {

        my_snake = new Snake({
            body: {
                offset: { x: 0, y: 0 },
                length: 30,
                points: Array.apply(null, { length: 10 }).map((v, i) => {
                    return { x: i, y: i }
                })
            },
            density: 20,
            speed: 15,
            sensitivity: 360,
            direction: 180
        });
        my_snake.importData(snake_info);
        // 生成第一视角蛇
        battlefield.addChild(my_snake);
        ani_ticker.add(() => {
            my_snake.run()

            var current_stage_scale = 25 / my_snake._density
            current_stage_scale < 1 && (current_stage_scale = 1);
            current_stage.scale.set(current_stage_scale, current_stage_scale);

            var head_point = my_snake.getHeadPoint();
            battlefield_view_width = VIEW_WIDTH / current_stage_scale
            battlefield_view_height = VIEW_HEIGHT / current_stage_scale
            ani_tween.Tween("battlefield", battlefield)
                .to({
                    x: -head_point.x + battlefield_view_width / 2,
                    y: -head_point.y + battlefield_view_height / 2
                }, S_ANI_TIME)
                .start();
            // battlefield.x = 
            // battlefield.y =

            foods.updatePos(battlefield.x, battlefield.y, my_snake._speed);

            //更新战场信息
            _deg_log.text = `FPS:${ani_ticker.FPS.toFixed(2)}
                        NAME:${my_snake._id}
                        X:${head_point.x.toFixed(5).substr(0, 7)}
                        Y:${head_point.y.toFixed(5).substr(0, 7)}
                        长度Body:${my_snake._body.length}
                        长度骨节数:${my_snake._body.points.length}
                        长度骨节长度:${my_snake._base_spacing}
                        腰围Density:${my_snake._density}
                        速度Speed:${my_snake._speed.toFixed(5).substr(0, 7)}
                        方向Direction:${my_snake._direction.toFixed(5).substr(0, 7)}
                        ${ -1 / Math.tan((my_snake._direction / 180 - 0.5) * Math.PI)}
                        灵敏度Sensitivity:${my_snake._sensitivity.toFixed(5).substr(0, 7)}
                        行为预测:${_is_Behavior_Prediction}
                        是否顺时针:${my_snake._is_clockwise}
                        ${my_snake._is_use_pre_points ? "补帧" : "跳帧"}
                        `;
            _deg_log.scale.set(1 / current_stage_scale, 1 / current_stage_scale);
            // //背景贴图位移
            // bg_img.tilePosition = battlefield.position
        });
        my_snake.viewSnake(snakes)
        //死亡监听
        var _send_die = false;
        my_snake.on("died", function (hit_snake) {
            if (_send_die) {
                return
            }
            _send_die = true;
            console.log("发送死亡信息")
            syncServerData("chat.chatHandler.dieSnake", {
                killer_id: hit_snake[0]._id
            }, function (data) {
                if (data.success) {
                    console.log("you died!");
                }
                //exit to re enter
            })
        });

        my_snake.viewFoods(foods);

        my_snake_inited(my_snake);

        // my_snake.alpha = 0.5

        return my_snake;
    }
    function my_snake_inited(my_snake: Snake) {

        /**缓存战场数据的范围·宽度 */
        const battlefield_cache_data_width = VIEW_WIDTH * 4;
        /**缓存战场数据的范围·高度 */
        const battlefield_cache_data_height = VIEW_HEIGHT * 4;
        /**目前战场数据的起点·X */
        var battlefield_cache_data_x;
        /**目前战场数据的起点·Y */
        var battlefield_cache_data_y;

        function getRangeFoods(center_point, cb?: (data: { foods: EatAbleFood[] }) => void) {
            battlefield_cache_data_x = center_point.x - battlefield_cache_data_width / 2;
            battlefield_cache_data_y = center_point.y - battlefield_cache_data_height / 2;

            syncServerData("chat.chatHandler.getRangeFoods", {
                x: battlefield_cache_data_x,
                y: battlefield_cache_data_y,
                width: battlefield_cache_data_width,
                height: battlefield_cache_data_height,
            }, function (data) {
                if (data.foods) {
                    foods._particle_foods = []
                    foods.clearParticleFood();
                    data.foods.forEach(food_info => {
                        foods.addParticleFood(new FoodEffect(food_info.effect), food_info.x, food_info.y)
                    });
                    cb && cb(data)
                }
            })
        }
        //初始化食物数据
        getRangeFoods(my_snake.getHeadPoint());

        var ping = 100;//网络延迟的毫秒数
        const VIEW_WIDTH_2 = VIEW_WIDTH / 2;
        const VIEW_HEIGHT_2 = VIEW_HEIGHT / 2;

        ani_ticker.add(() => {
            // 缓存数据所需的边境
            var cache_check_range = (ping + 500/*假设下载数据需要500ms*/) * 0.001 * my_snake._speed;
            var head_point = my_snake.getHeadPoint();
            if (
                head_point.x - VIEW_WIDTH_2 < battlefield_cache_data_x ||
                head_point.y - VIEW_HEIGHT_2 < battlefield_cache_data_y ||
                head_point.x + VIEW_WIDTH_2 + cache_check_range > battlefield_cache_data_x + battlefield_cache_data_width ||
                head_point.y + VIEW_HEIGHT_2 + cache_check_range > battlefield_cache_data_y + battlefield_cache_data_height
            ) {
                getRangeFoods(head_point)
            }
        });


        /**进食 */
        function eatFoods(foods, cb) {
            syncServerData("chat.chatHandler.eatFoods", {
                foods
            }, function (data, get_delay_time) {
                cb && cb(data)
                // _is_Behavior_Prediction && my_snake.update(get_delay_time());
            });
        }
        // 触发吃食物
        my_snake.on("eated_food", function (eated_points) {
            my_snake.waitingForImportData();
            var points = eated_points.map(food => {
                return {
                    x: food.x,
                    y: food.y
                }
            });
            eatFoods(points, function (data) {
                my_snake.importData(data);
            });
        })
        init_w.ok(0, []);
    };

    var _deg_log = new PIXI.Text("", { font: "16px 微软雅黑", fill: "#0FF" });
    current_stage.addChild(_deg_log);

    // var mask = SVGGraphics.importFromSVG(`<rect x="0" y="0" width="${VIEW_WIDTH}" height="${VIEW_HEIGHT}" fill="rgba(255,255,255,${0.2})" stroke-width="0"/>`)._graphics;
    var mask = new PIXI.Sprite(resource["bg_normal"].texture);
    mask.width = VIEW_WIDTH
    mask.height = VIEW_HEIGHT
    mask.alpha = 0;
    current_stage.addChild(mask);

    mask.interactive = true;

    var _is_loading_data = false;
    var _is_Behavior_Prediction = true;
    on(mask, "mousemove|tap", function (e: PIXI.interaction.InteractionEvent) {
        if (!my_snake) {
            return
        }
        if (_is_loading_data || my_snake._delay_deg) {
            return;
        }
        var click_point = e.data.getLocalPosition(this.parent);
        var deg = Math.atan2(click_point.x - battlefield_view_width / 2, click_point.y - battlefield_view_height / 2);
        if (deg < 0) {
            deg = Math.PI * 2 + deg;
        }

        deg = deg / Math.PI * 180
        // my_snake.turnHead(deg);
        _is_loading_data = true;
        //蛇的速度变慢，以避免服务端数据返回的时候的跳跃感
        my_snake.waitingForImportData()
        syncServerData("chat.chatHandler.turnMySnakeHead", {
            deg: deg,
        }, function (data, get_delay_time) {
            // my_snake.importData(data);
            // _is_Behavior_Prediction && my_snake.update(get_delay_time());
            _is_loading_data = false;
        })
    });
    on(mask, "mousedown", function (e: PIXI.interaction.InteractionEvent) {
        _is_Behavior_Prediction = !_is_Behavior_Prediction;
    });

    var is_sprinting = false;
    on(mask, "mousedown", function (e: PIXI.interaction.InteractionEvent) {
        if (!my_snake) {
            return
        }
        syncServerData("chat.chatHandler.snakeSprint", {}, function (is_success) {
            if (is_success) {
                console.log("冲刺成功");
                is_sprinting = true;
            } else {
                console.log("冲刺失败");
            }
        });
    });
    on(mask, "mouseup|mouseover", function (e: PIXI.interaction.InteractionEvent) {
        if (!my_snake || !is_sprinting) {
            return
        }
        syncServerData("chat.chatHandler.stopSnakeSprint", {}, function (is_success) {
            console.log(is_success ? "停止冲刺" : "停止冲刺失败")
        });
    });

    // 远程数据相关

    function showError(error) {
        console.log(error)
    }

    function queryEntry(uid, callback) {
        var route = 'gate.gateHandler.queryEntry';
        pomelo.init({
            host: window.location.hostname,
            port: 3014,
            log: false
        }, function () {
            pomelo.request(route, {
                uid: uid
            }, function (data) {
                // pomelo.disconnect();
                if (data.code === 500) {
                    showError("登陆失败");
                    return;
                }
                callback(data.host, data.port);
            });
        });
    };

    var username = "gaubee-" + Math.random().toString(36).substr(2);
    var rid = "fangjian-1";
    queryEntry(username, function (host, port) {
        pomelo.init({
            host: host,
            port: port,
            log: false
        }, function () {
            var route = "connector.entryHandler.enter";
            pomelo.request(route, {
                username: username,
                rid: rid
            }, function (data) {
                if (data.error) {
                    showError("重复登陆！");
                    return;
                }
                initSnake();
            });
        });
    });
    function initSnake() {
        syncServerData("chat.chatHandler.getMySnake", {
            rid: rid,
            from: username
        }, function (data, get_delay_time) {
            // battlefield.emit("my_snake_init", data);
            var snake = my_snake_init(data);
            _is_Behavior_Prediction && snake.update(get_delay_time())
        });
        syncServerData("chat.chatHandler.getOtherSnakes", {
            rid: rid,
            from: username
        }, function (data, get_delay_time) {
            data.snakes && data.snakes.forEach(function (snake_data) {
                var new_snake = joinSnake(snake_data);
                _is_Behavior_Prediction && new_snake.update(get_delay_time())
            });
        });
    }

    pomelo.on("turnHead", function (data) {
        if (data.id === my_snake._id) {
            my_snake.importData(data)
        } else {
            snakes.children.forEach((snake: Snake) => {
                snake._id === data.id && snake.importData(data)
            });
        }
    });

    function joinSnake(new_snake_data) {
        var new_snake = new Snake({
            body: {
                offset: { x: 0, y: 0 },
                length: 20,
                points: Array.apply(null, { length: 3 }).map((v, i) => {
                    return { x: 0, y: 0 }
                })
            },
            density: 20,
            speed: 10,
            sensitivity: 360,
            direction: 0
        });
        ani_ticker.add(() => {
            // new_snake._direction = (new_snake._direction + Math.random() * 5) % 360;
            new_snake.run();
        });
        new_snake.importData(new_snake_data);
        snakes.addSnake(new_snake);
        return new_snake;
    };

    pomelo.on("joinSnake", function (new_snake_data) {
        if (my_snake._id === new_snake_data.id) {
            return
        }
        joinSnake(new_snake_data);
    });

    pomelo.on("foodBeEated", function (data) {
        var snake_data = data.snake;
        if (snake_data.id === my_snake._id) {
            return
        }
        snakes.children.some((snake: Snake) => {
            if (snake._id === snake_data.id) {
                snake.importData(snake_data);
                return true;
            }
        });
        data.foods.forEach(function (food_info) {
            foods.removeParticleFood(food_info.x, food_info.y)
        });
    });

    pomelo.on("dieSnake", function (data) {
        if (data.snake_id === my_snake._id) {
            my_snake.die();
            // alert("死亡！")
        } else {
            snakes.children.some((snake: Snake) => {
                if (snake._id === data.snake_id) {
                    snake.die()
                    return true;
                }
            });
        }
        data.foods.forEach(function (food_info) {
            foods.addParticleFood(new FoodEffect(food_info.effect), food_info.x, food_info.y)
        });
    });

    pomelo.on("burnSnake", function (data) {
        data.foods.forEach(function (food_info) {
            foods.addParticleFood(new FoodEffect(food_info.effect), food_info.x, food_info.y)
        });
        if (data.snake_id === my_snake._id) {
            my_snake._delay_num -= data.burn_body;
        } else {
            snakes.children.some((snake: Snake) => {
                if (snake._id === data.snake_id) {
                    snake._delay_num -= data.burn_body;
                    return true;
                }
            });
        }
    });

    function importSnakeData(data) {
        if (data.id === my_snake._id) {
            my_snake.importData(data)
        } else {
            snakes.children.some((snake: Snake) => {
                if (snake._id === data.id) {
                    snake.importData(data);
                    return true;
                }
            });
        }
    };
    pomelo.on("snakeSprint", importSnakeData);
    pomelo.on("snakeStopSprint", importSnakeData);
}

current_stage.on("init", initStage);

const init_w = new When(2, () => {
    ani_tween.start();
    jump_tween.start();
    ani_ticker.start();
});
export function initStage() {
    init_w.ok(1, []);
}
